package me.flyray.bsin.server.biz;


import com.alibaba.cloud.ai.advisor.RetrievalRerankAdvisor;
import com.alibaba.cloud.ai.memory.redis.RedissonRedisChatMemoryRepository;
import com.alibaba.cloud.ai.model.RerankModel;
import me.flyray.bsin.domain.entity.AgentCard;
import me.flyray.bsin.domain.entity.Conversation;
import me.flyray.bsin.domain.entity.ConversationMessage;
import me.flyray.bsin.domain.enums.AIAgentChoreographyType;
import me.flyray.bsin.domain.request.AppChatDTO;
import me.flyray.bsin.infrastructure.mapper.AgentCardMapper;
import me.flyray.bsin.infrastructure.mapper.ConversationMapper;
import me.flyray.bsin.infrastructure.mapper.ConversationMessageMapper;
import me.flyray.bsin.server.config.McpHealthCheckConfig;
import me.flyray.bsin.server.ws.WsServerEndpoint;
import me.flyray.bsin.utils.BsinSnowflake;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;

import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.util.Arrays;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import me.flyray.bsin.context.BsinServiceContext;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.ObjectMapper;

@Slf4j
@Service
public class AppAgentEngine {

    // 常量定义
    private static final String CHART_KEYWORD = "图表";
    private static final String DONE_MARKER = "[DONE]";
    private static final String ERROR_MARKER = "[ERROR]";
    private static final String[] NON_STREAMING_TYPES = {"sync", "non-streaming", "0"};
    
    // 业务类型常量
    private static final String RESPONSE_TYPE_RECOMMENDED_INFO = "recommendedInfo";
    private static final String FIELD_RECOMMENDED_INFO = "recommendedInfo";
    private static final String FIELD_GOODS = "goods";
    private static final String FIELD_PRODUCTS = "products";
    private static final String FIELD_STORES = "stores";
    private static final String FIELD_LOCATIONS = "locations";
    private static final String FIELD_COUPONS = "coupons";
    private static final String FIELD_DISCOUNTS = "discounts";
    
    // 字段名常量
    private static final String FIELD_GOODS_NO = "goodsNo";
    private static final String FIELD_GOODS_NAME = "goodsName";
    private static final String FIELD_BRAND = "brand";
    private static final String FIELD_STOCK = "stock";
    private static final String FIELD_STORE_NAME = "storeName";
    private static final String FIELD_STORE_NO = "storeNo";
    private static final String FIELD_ADDRESS = "address";
    private static final String FIELD_COUPON_NAME = "couponName";
    private static final String FIELD_COUPON_NO = "couponNo";
    private static final String FIELD_VALIDITY_PERIOD = "validityPeriod";
    
    // 默认值常量
    private static final String DEFAULT_BRAND = "未知品牌";
    private static final int DEFAULT_STOCK = 100;
    private static final String DEFAULT_ADDRESS = "地址信息待补充";
    private static final String DEFAULT_VALIDITY_PERIOD = "有效期待确认";
    private static final String DEFAULT_DESCRIPTION = "AI智能推荐结果";
    private static final String DEFAULT_TENANT_ID = "default";
    
    // JSON解析器 - 静态实例，线程安全
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private final ChatModel chatModel;
    private final VectorStore vectorStore;
    private final RerankModel rerankModel;
    private final ToolCallbackProvider tools;
    private final MessageWindowChatMemory messageWindowChatMemory;
    private final int MAX_MESSAGES = 100;

    // 推荐的系统提示词模板
    @Value("classpath:/prompts/system-qa.st")
    private Resource systemResource;
    // 系统操作的提示词模板
    @Value("classpath:/prompts/system-qa.st")
    private Resource systemOpResource;
    @Value("classpath:/prompts/BI.txt")
    private Resource biTxt;

    @Value("classpath:/prompts/goodsRecommendation.txt")
    private Resource goodsRecommendation;
    @Value("classpath:/prompts/crmOpPromptTemplate.txt")
    private Resource crmOpPromptTemplate;

    @Autowired
    private ConversationMapper conversationMapper;
    @Autowired
    private ConversationMessageMapper conversationMessageMapper;
    @Autowired
    private AgentCardMapper agentCardMapper;
    @Autowired
    private McpHealthCheckConfig mcpHealthCheckConfig;

    public AppAgentEngine(@Qualifier("dashscopeChatModel") ChatModel chatModel, VectorStore vectorStore, RerankModel rerankModel, @Qualifier("loadbalancedMcpAsyncToolCallbacks") ToolCallbackProvider tools, RedissonRedisChatMemoryRepository redissonRedisChatMemoryRepository) {
        this.chatModel = chatModel;
        this.vectorStore = vectorStore;
        this.rerankModel = rerankModel;
        this.tools = tools;
        this.messageWindowChatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(redissonRedisChatMemoryRepository)
                .maxMessages(MAX_MESSAGES)
                .build();

        // 启动时检查 MCP 服务状态
        checkMcpServiceStatus();
    }

    /**
     * 检查 MCP 服务状态
     */
    private void checkMcpServiceStatus() {
        try {
            if (isMcpToolsAvailable()) {
                log.info("MCP服务状态检查通过，工具可用");
            } else {
                log.warn("MCP服务状态检查失败，将在运行时使用降级处理");
            }
        } catch (Exception e) {
            log.warn("MCP服务状态检查异常: {}", e.getMessage());
        }
    }

    /**
     * 1、根据不同的智能体参数，获取ChatClient，根据模型和工具
     * 2、进行模型推理对话
     * 3、LLM识别用户意图，基于不同的意图动态使用不同的提示词模板
     * 4、根据意图提示词模板进行解决意图需求的对话
     * @param wsServerEndpoint
     * @param agentCard
     * @param aiChatDTOReq
     */
    public void handleSingleAgent(WsServerEndpoint wsServerEndpoint, AgentCard agentCard, AppChatDTO aiChatDTOReq){
        String conversationNo = aiChatDTOReq.getConversationNo();
        processAgentChat(aiChatDTOReq, conversationNo, agentCard, AIAgentChoreographyType.SINGLE_AGENT, wsServerEndpoint);
    }

    public void handleMultiAgent(WsServerEndpoint wsServerEndpoint, AgentCard agentCard, AppChatDTO aiChatDTOReq){
        String conversationNo = BsinSnowflake.getId();
        processAgentChat(aiChatDTOReq, conversationNo, agentCard, AIAgentChoreographyType.MULTI_AGENT, wsServerEndpoint);
    }

    /**
     * 处理单智能体对话 - 非流式版本，返回完整响应
     * @param requestMap 请求参数
     * @return AI响应内容
     */
    public String handleSingleAgent(Map<String, Object> requestMap){
        AppChatDTO chatRequest = BsinServiceContext.getReqBodyDto(AppChatDTO.class, requestMap);
        String conversationNo = MapUtils.getString(requestMap, "conversationNo", BsinSnowflake.getId());
        String rawResponse = processAgentChatSync(chatRequest, conversationNo, AIAgentChoreographyType.SINGLE_AGENT);
        
        // 返回标准格式的响应，确保与WebSocket模式一致
        return buildStandardResponse(rawResponse);
    }

    /**
     * 处理多智能体对话 - 非流式版本，返回完整响应
     * @param requestMap 请求参数
     * @return AI响应内容
     */
    public String handleMultiAgent(Map<String, Object> requestMap){
        AppChatDTO chatRequest = BsinServiceContext.getReqBodyDto(AppChatDTO.class, requestMap);
        String conversationNo = MapUtils.getString(requestMap, "conversationNo", BsinSnowflake.getId());
        String rawResponse = processAgentChatSync(chatRequest, conversationNo, AIAgentChoreographyType.MULTI_AGENT);
        
        // 返回标准格式的响应，确保与WebSocket模式一致
        return buildStandardResponse(rawResponse);
    }

    /**
     * WebSocket处理入口 - 支持流式和非流式选择
     */
    private void processAgentChat(AppChatDTO chatRequest, String conversationNo, AgentCard agentCard,
                                 AIAgentChoreographyType agentType, WsServerEndpoint wsServerEndpoint) {
        String message = chatRequest.getQuestion();
        String tenantId = chatRequest.getTenantId();
        String fromNo = chatRequest.getFromNo();
        String agentNo = chatRequest.getToNo();
        
        log.info("智能体对话开始 - AgentType: {}, FromNo: {}, ToNo: {}", agentType, fromNo, agentNo);
        
        // 保存用户消息
        String actualConversationNo = saveUserMessage(tenantId, fromNo, agentCard, conversationNo, message);
        if (actualConversationNo != null) {
            conversationNo = actualConversationNo; // 更新会话ID
        }
        
        // 统一处理逻辑，只是输出方式不同
        boolean useStreaming = shouldUseStreaming(chatRequest);
        log.info("处理模式选择 - UseStreaming: {}", useStreaming);
        
        try {
            processAgentResponse(chatRequest, agentType, useStreaming, wsServerEndpoint, conversationNo);
        } catch (IOException e) {
            log.error("处理智能体响应失败", e);
            throw new RuntimeException("处理智能体响应失败: " + e.getMessage(), e);
        }
        
        log.info("智能体对话完成 - FromNo: {}, ToNo: {}", fromNo, agentNo);
    }

    /**
     * HTTP处理入口 - 使用相同的核心逻辑，支持流式选择
     */
    private String processAgentChatSync(AppChatDTO chatRequest, String conversationNo, 
                                       AIAgentChoreographyType agentType) {
        String message = chatRequest.getQuestion();
        String tenantId = chatRequest.getTenantId();
        String bizRoleType = chatRequest.getBizRoleType();
        String bizRoleTypeNo = chatRequest.getBizRoleTypeNo();
        String fromNo = chatRequest.getFromNo();
        String agentNo = chatRequest.getToNo();
        
        log.info("HTTP智能体处理开始 - AgentType: {}, FromNo: {}, ToNo: {}", agentType, fromNo, agentNo);
        
        // 保存用户消息
        String actualConversationNo = saveUserMessage(tenantId, fromNo, null, conversationNo, message);
        if (actualConversationNo != null) {
            conversationNo = actualConversationNo; // 更新会话ID
        }
        
        // HTTP模式下也判断是否使用流式处理（但最终都返回完整响应）
        boolean useStreaming = shouldUseStreaming(chatRequest);
        boolean canStream = canUseStreamingInHttp(message);
        log.info("HTTP处理模式 - UseStreaming: {}, CanStream: {}", useStreaming, canStream);
        
        // 使用相同的核心逻辑
        String responseText;
        if (useStreaming && canStream) {
            log.debug("使用HTTP内部流式处理");
            responseText = processStreamingAndWait(tenantId, message, agentType);
        } else {
            log.debug("使用HTTP直接处理");
            responseText = getAgentResponse(tenantId, bizRoleTypeNo, bizRoleType, message, agentType);
        }
        
        log.info("HTTP智能体处理完成 - ResponseLength: {}", responseText.length());
        
        // 保存AI响应
        saveAIMessage(tenantId, fromNo, agentNo, conversationNo, responseText);
        
        return responseText;
    }

    /**
     * 判断HTTP模式下是否可以使用流式处理
     */
    private boolean canUseStreamingInHttp(String message) {
        // HTTP模式下，对于复杂问题可以内部使用流式处理来提高响应质量
        return !message.contains(CHART_KEYWORD) && message.length() > 20;
    }

    /**
     * HTTP流式处理并等待完成
     */
    private String processStreamingAndWait(String tenantId, String message, AIAgentChoreographyType agentType) {
        if (agentType == AIAgentChoreographyType.SINGLE_AGENT) {
            // 内部使用流式处理，但收集完整响应后返回
            ChatClient chatClient = getChatClient(AIAgentChoreographyType.SINGLE_AGENT, message);
            StringBuilder fullResponse = new StringBuilder();
            
            // 这里可以使用CompletableFuture等待流式处理完成
            // 目前简化为直接调用同步版本
            return chatClient.prompt().user(message).call().chatResponse()
                .getResult().getOutput().getText();
        } else {
            return getMultiAgentResponse(tenantId, message);
        }
    }

    /**
     * 获取智能体响应 - 核心业务逻辑，同步异步共用
     */
    private String getAgentResponse(String tenantId, String bizRoleTypeNo, String bizRoleType, String message, AIAgentChoreographyType agentType) {
        if (agentType == AIAgentChoreographyType.SINGLE_AGENT) {
            return getSingleAgentResponse(tenantId, bizRoleTypeNo, bizRoleType, message);
        } else {
            return getMultiAgentResponse(tenantId, message);
        }
    }

    /**
     * 单智能体响应生成 - 核心逻辑（优化版本）
     */
    private String getSingleAgentResponse(String tenantId, String bizRoleTypeNo, String bizRoleType, String message) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 特殊消息处理
            if (message.contains(CHART_KEYWORD)) {
                log.info("处理特殊消息: 包含图表关键词");
                return getBIResponse();
            }
            
            // 常规处理 - 使用优化后的方式
            logTenantInfo(tenantId, "LLM处理开始", message);
            ChatClient chatClient = getChatClient(AIAgentChoreographyType.SINGLE_AGENT, message);

            // 动态识别意图获取提示词模板
            Prompt prompt;
            try {
                prompt = createPrompt(tenantId, bizRoleTypeNo, bizRoleType, message);
            } catch (IOException e) {
                log.error("创建提示词模板失败", e);
                throw new RuntimeException("创建提示词模板失败: " + e.getMessage(), e);
            }
            
            // 调用大模型
            String response = chatClient.prompt(prompt)
                .call()
                .chatResponse()
                .getResult()
                .getOutput()
                .getText();
                
            long endTime = System.currentTimeMillis();
            logTenantInfo(tenantId, "LLM处理完成", 
                String.format("ResponseLength: %d, Content: %s, 耗时: %dms", 
                    response.length(), response.substring(0, Math.min(200, response.length())), (endTime - startTime)));
            
            return response;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            logTenantInfo(tenantId, "LLM处理失败", 
                String.format("耗时: %dms, 错误: %s", (endTime - startTime), e.getMessage()));
            
            // 检查是否是 MCP 相关错误，提供降级处理
            if (isMcpRelatedError(e)) {
                log.warn("检测到MCP相关错误，尝试降级处理 - TenantId: {}, Error: {}", tenantId, e.getMessage());
                return handleMcpFallback(tenantId, message);
            }
            
            throw new RuntimeException("AI处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查是否是 MCP 相关错误
     */
    private boolean isMcpRelatedError(Exception e) {
        String errorMessage = e.getMessage();
        return errorMessage != null && (
            errorMessage.contains("No McpAsyncClient available") ||
            errorMessage.contains("McpAsyncClient") ||
            errorMessage.contains("LoadbalancedMcpAsyncClient") ||
            errorMessage.contains("MCP")
        );
    }

    /**
     * MCP 降级处理
     */
    private String handleMcpFallback(String tenantId, String message) {
        try {
            log.info("执行MCP降级处理 - TenantId: {}, Message: {}", tenantId, message);
            
            // 使用基础 ChatClient（不包含 MCP 工具）
            ChatClient fallbackClient = ChatClient.builder(chatModel).build();
            
            // 创建基础提示词
            Prompt fallbackPrompt = createFallbackPrompt(tenantId, message);
            
            // 调用大模型
            String response = fallbackClient.prompt(fallbackPrompt)
                .call()
                .chatResponse()
                .getResult()
                .getOutput()
                .getText();
                
            log.info("MCP降级处理成功 - TenantId: {}, ResponseLength: {}", tenantId, response.length());
            return response;
            
        } catch (Exception fallbackError) {
            log.error("MCP降级处理也失败 - TenantId: {}, Error: {}", tenantId, fallbackError.getMessage(), fallbackError);
            return "抱歉，系统暂时无法处理您的请求，请稍后重试。";
        }
    }

    /**
     * 创建降级处理的提示词
     */
    private Prompt createFallbackPrompt(String tenantId, String message) throws IOException {
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
        Map<String, Object> systemParams = new HashMap<>();
        systemParams.put("format_requirements", "请以简洁明了的方式回答用户问题");
        systemParams.put("response_type", "text");
        systemParams.put("tenantId", validateTenantId(tenantId));
        systemParams.put("question_answer_context", "");
        
        Message systemMessage = systemPromptTemplate.createMessage(systemParams);
        UserMessage userMessage = new UserMessage(message);
        
        return new Prompt(List.of(systemMessage, userMessage));
    }

    /**
     * 获取BI响应
     */
    private String getBIResponse() {
        try {
            String biContent = biTxt.getContentAsString(StandardCharsets.UTF_8);
            log.info("BI文件内容读取成功 - Length: {}", biContent.length());
            return biContent;
        } catch (IOException e) {
            log.error("读取BI文件内容失败", e);
            return "BI文件内容加载失败";
        }
    }

    /**
     * 意图识别，动态创建提示词模板：根据消息内容智能选择模板
     * 创建Prompt对象 - 提取公共逻辑
     */
    private Prompt createPrompt(String tenantId, String bizRoleTypeNo, String bizRoleType, String message) throws IOException {
        // 意图识别，动态选择提示词模板
        String formatRequirements = getFormatRequirementsByIntent(message);
        
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
        Map<String, Object> systemParams = new HashMap<>();
        systemParams.put("format_requirements", formatRequirements);
        systemParams.put("response_type", RESPONSE_TYPE_RECOMMENDED_INFO);
        systemParams.put("tenantId", validateTenantId(tenantId));
        systemParams.put("bizRoleTypeNo", bizRoleTypeNo != null ? bizRoleTypeNo : "");
        systemParams.put("bizRoleType", bizRoleType != null ? bizRoleType : "");
        systemParams.put("question_answer_context", ""); // 添加缺失的变量
        
        Message systemMessage = systemPromptTemplate.createMessage(systemParams);
        UserMessage userMessage = new UserMessage(message);
        
        return new Prompt(List.of(systemMessage, userMessage));
    }

    /**
     * 根据消息内容智能识别意图，返回对应的格式要求模板
     */
    private String getFormatRequirementsByIntent(String message) throws IOException {
        if (org.apache.commons.lang3.StringUtils.isBlank(message)) {
            log.debug("消息为空，使用默认商品推荐模板");
            return goodsRecommendation.getContentAsString(StandardCharsets.UTF_8);
        }
        
        String lowerMessage = message.toLowerCase();
        
        // 商品推荐相关关键词
        String[] goodsKeywords = {"推荐", "商品", "产品", "购买", "销售", "价格", "库存", "热销", "新品", "促销", "优惠"};
        // 客户管理相关关键词  
        String[] customerKeywords = {"客户", "用户", "会员", "联系人", "信息", "资料", "档案", "管理", "新增", "编辑", "删除", "查询"};
        
        // 检查是否包含商品推荐关键词
        boolean isGoodsIntent = Arrays.stream(goodsKeywords)
            .anyMatch(keyword -> lowerMessage.contains(keyword));
            
        // 检查是否包含客户管理关键词
        boolean isCustomerIntent = Arrays.stream(customerKeywords)
            .anyMatch(keyword -> lowerMessage.contains(keyword));
        
        // 根据意图选择模板
        if (isGoodsIntent && !isCustomerIntent) {
            log.info("检测到商品推荐意图，使用商品推荐模板 - Message: {}", message.substring(0, Math.min(50, message.length())));
            return goodsRecommendation.getContentAsString(StandardCharsets.UTF_8);
        } else if (isCustomerIntent && !isGoodsIntent) {
            log.info("检测到客户管理意图，使用客户管理模板 - Message: {}", message.substring(0, Math.min(50, message.length())));
            return crmOpPromptTemplate.getContentAsString(StandardCharsets.UTF_8);
        } else if (isGoodsIntent && isCustomerIntent) {
            // 如果同时包含两种意图，优先使用客户管理模板（更具体）
            log.info("检测到混合意图，优先使用客户管理模板 - Message: {}", message.substring(0, Math.min(50, message.length())));
            return crmOpPromptTemplate.getContentAsString(StandardCharsets.UTF_8);
        } else {
            // 默认使用商品推荐模板
            log.info("未检测到明确意图，使用默认商品推荐模板 - Message: {}", message.substring(0, Math.min(50, message.length())));
            return goodsRecommendation.getContentAsString(StandardCharsets.UTF_8);
        }
    }



    /**
     * 验证和处理租户ID
     */
    private String validateTenantId(String tenantId) {
        if (org.apache.commons.lang3.StringUtils.isBlank(tenantId)) {
            log.warn("租户ID为空，使用默认租户ID: {}", DEFAULT_TENANT_ID);
            return DEFAULT_TENANT_ID;
        }
        log.debug("使用租户ID: {}", tenantId);
        return tenantId;
    }

    /**
     * 记录租户相关的处理信息
     */
    private void logTenantInfo(String tenantId, String operation, String message) {
        String validTenantId = validateTenantId(tenantId);
        log.info("租户操作 - TenantId: {}, Operation: {}, Message: {}", validTenantId, operation, message);
    }

    /**
     * 多智能体响应生成 - 核心逻辑
     */
    private String getMultiAgentResponse(String tenantId, String message) {
        // 多智能体协作场景，通常返回结构化数据
        return "{\"collaboration\":\"多智能体协作\",\"status\":\"处理中\",\"message\":\"收到问题：" + message + "，正在为您提供最佳解答...\"}";
    }

    /**
     * 判断是否使用流式处理
     */
    private boolean shouldUseStreaming(AppChatDTO chatRequest) {
        String chatType = chatRequest.getChatType();
        String message = chatRequest.getQuestion();
        
        // 1. 明确指定非流式
        if (Arrays.asList(NON_STREAMING_TYPES).contains(chatType)) {
            return false;
        }
        
        // 2. 特殊消息不使用流式（响应很快）
        if (message.contains(CHART_KEYWORD)) {
            return false;
        }
        
        // 3. 短消息不使用流式
        if (message != null && message.length() < 10) {
            return false;
        }
        
        // 4. 默认使用流式处理
        return true;
    }

    /**
     * 统一的智能体响应处理 - 核心逻辑相同，只是输出方式不同
     */
    private void processAgentResponse(AppChatDTO chatRequest, AIAgentChoreographyType agentType, boolean useStreaming,
                                    WsServerEndpoint wsServerEndpoint, String conversationNo) throws IOException {
        if (agentType == AIAgentChoreographyType.SINGLE_AGENT) {
            processSingleAgentUnified(chatRequest, useStreaming, wsServerEndpoint, conversationNo);
        } else {
            processMultiAgentUnified(chatRequest, useStreaming, wsServerEndpoint, conversationNo);
        }
    }

    /**
     * 单智能体统一处理 - 使用相同核心逻辑
     */
    private void processSingleAgentUnified(AppChatDTO chatRequest, boolean useStreaming, WsServerEndpoint wsServerEndpoint,
                                          String conversationNo) throws IOException {
        String message = chatRequest.getQuestion();
        String tenantId = chatRequest.getTenantId();
        String bizRoleTypeNo = chatRequest.getBizRoleTypeNo();
        String bizRoleType = chatRequest.getBizRoleType();
        String fromNo = chatRequest.getFromNo();
        String agentNo = chatRequest.getToNo();
        
        if (useStreaming && wsServerEndpoint != null && !message.contains(CHART_KEYWORD)) {
            // 流式输出 - 使用优化后的方式
            log.info("开始流式处理 - MessageLength: {}, TenantId: {}", message.length(), tenantId);
            ChatClient chatClient = getChatClient(AIAgentChoreographyType.SINGLE_AGENT, message);
            Prompt prompt;
            try {
                prompt = createPrompt(tenantId, bizRoleTypeNo, bizRoleType, message);
            } catch (IOException e) {
                log.error("创建提示词模板失败", e);
                throw new RuntimeException("创建提示词模板失败: " + e.getMessage(), e);
            }
            
            log.debug("流式处理系统提示词加载完成 - TenantId: {}", tenantId);
                
            StringBuilder fullResponse = new StringBuilder();
            
            // 流式调用
            chatClient.prompt(prompt)
                .stream()
                .chatResponse()
                .subscribe(
                    chatResponse -> {
                        String content = chatResponse.getResult().getOutput().getText();
                        log.debug("流式响应片段 - Length: {}, TenantId: {}", content.length(), tenantId);
                        
                        // 构建标准格式的流式响应
                        String standardChunk = buildStandardResponseChunk(content);
                        wsServerEndpoint.sendMessageAsync(standardChunk);
                        
                        fullResponse.append(content);
                    },
                    error -> {
                        log.error("流式处理异常 - TenantId: {}", tenantId, error);
                        wsServerEndpoint.sendMessageAsync("[DONE]");
                    },
                    () -> {
                        log.info("流式处理完成 - TotalLength: {}, TenantId: {}", fullResponse.length(), tenantId);
                        
                        try {
                            // 发送最终的标准格式完整响应
                            String finalStandardResponse = buildStandardResponse(fullResponse.toString());
                            wsServerEndpoint.sendMessageAsync(finalStandardResponse);
                            
                            // 等待一小段时间确保消息发送完成
                            Thread.sleep(50);
        
                            // 发送结束标识
                            wsServerEndpoint.sendMessageAsync("[DONE]");
                        } catch (Exception e) {
                            log.error("发送最终响应失败 - TenantId: {}", tenantId, e);
                        }
                        
                        // 保存原始AI响应到数据库
                        saveAIMessage(tenantId, fromNo, agentNo, conversationNo, fullResponse.toString());
                    }
                );
        } else {
            // 非流式输出 - 使用相同的核心响应生成逻辑
            log.info("开始非流式处理 - TenantId: {}, Message: {}", tenantId, message);
            try {
                String response = getSingleAgentResponse(tenantId, bizRoleTypeNo, bizRoleType, message);
                log.info("非流式处理完成 - ResponseLength: {}, TenantId: {}", response.length(), tenantId);
                sendResponse(response, useStreaming, wsServerEndpoint);
                saveAIMessage(tenantId, fromNo, agentNo, conversationNo, response);
                log.info("非流式处理全部完成 - TenantId: {}", tenantId);
            } catch (Exception e) {
                log.error("非流式处理异常 - TenantId: {}, Message: {}", tenantId, message, e);
                throw e;
            }
        }
    }

    /**
     * 多智能体统一处理 - 使用相同核心逻辑
     */
    private void processMultiAgentUnified(AppChatDTO chatRequest, boolean useStreaming, WsServerEndpoint wsServerEndpoint,
                                        String conversationNo) {
        String message = chatRequest.getQuestion();
        String tenantId = chatRequest.getTenantId();
        String fromNo = chatRequest.getFromNo();
        String agentNo = chatRequest.getToNo();
        
        log.info("开始多智能体处理");
        // 使用相同的核心响应生成逻辑
        String response = getMultiAgentResponse(tenantId, message);
        log.info("多智能体处理完成 - ResponseLength: {}", response.length());
        sendResponse(response, useStreaming, wsServerEndpoint);
        saveAIMessage(tenantId, fromNo, agentNo, conversationNo, response);
    }

    /**
     * 统一的响应发送方法
     */
    private void sendResponse(String response, boolean useStreaming, WsServerEndpoint wsServerEndpoint) {
        if (wsServerEndpoint != null) {
            try {
                // 构建标准响应格式
                String standardResponse = buildStandardResponse(response);
                log.info("发送WebSocket响应 - Length: {}, Content: {}", 
                    standardResponse.length(), 
                    response.substring(0, Math.min(100, response.length())));
                
                // 发送主要响应
                wsServerEndpoint.sendMessageAsync(standardResponse);
                
                // 等待一小段时间确保消息发送完成
                Thread.sleep(50);
                
                // 发送结束标识
                wsServerEndpoint.sendMessageAsync("[DONE]");
                log.info("WebSocket响应发送完成");
            } catch (Exception e) {
                log.error("发送WebSocket响应失败", e);
            }
        } else {
            log.warn("WebSocket端点为null，无法发送响应");
        }
        // HTTP模式下响应通过return返回
    }
    
    /**
     * 构建标准响应格式块 - 用于流式处理
     */
    private String buildStandardResponseChunk(String content) {
        try {
            // 尝试解析JSON，如果是JSON则使用JSON格式，否则使用字符串格式
            if (content.trim().startsWith("[") || content.trim().startsWith("{")) {
                // 可能是JSON格式，验证一下
                try {
                    var jsonNode = OBJECT_MAPPER.readTree(content);
                    
                    // 智能提取关键内容
                    String extractedContent = extractKeyContent(jsonNode);
                    if (extractedContent != null) {
                        // 使用提取的关键内容
                        String description = extractDescription(content);
                        return "{\"type\":\"2\",\"bizType\":\"1\",\"description\":\"" + escapeJsonString(description) + "\",\"content\":" + extractedContent + "}";
                    }
                    
                    // JSON格式正确，但没有找到关键字段，使用原始内容
                    String description = extractDescription(content);
                    return "{\"type\":\"3\",\"bizType\":\"1\",\"description\":\"" + escapeJsonString(description) + "\",\"content\":" + content + "}";
                } catch (Exception e) {
                    // JSON格式错误，降级为字符串
                    log.warn("JSON格式验证失败，降级为字符串: {}", e.getMessage());
                    return "{\"type\":\"1\",\"bizType\":\"1\",\"description\":\"文本内容\",\"content\":\"" + escapeJsonString(content) + "\"}";
                }
            } else {
                // 纯文本内容，使用字符串类型
                return "{\"type\":\"1\",\"bizType\":\"1\",\"description\":\"文本内容\",\"content\":\"" + escapeJsonString(content) + "\"}";
            }
        } catch (Exception e) {
            log.warn("构建标准响应格式块失败，使用默认字符串格式: {}", e.getMessage());
            return "{\"type\":\"1\",\"bizType\":\"1\",\"description\":\"响应格式构建失败\",\"content\":\"" + escapeJsonString(content) + "\"}";
        }
    }

    /**
     * 处理聊听内容
     * @param aiChatDTOReq
     * @param webSocketServer
     */
    public void chat(AppChatDTO aiChatDTOReq, WsServerEndpoint webSocketServer) {
        // 根据toNo查找对应智能体
        AgentCard agentCard = agentCardMapper.selectById(aiChatDTOReq.getToNo());
        agentCard.setAgentType("1");
        AIAgentChoreographyType aiAgentType = AIAgentChoreographyType.getInstanceById(agentCard.getAgentType());
        // 判断枚举什么类型，不同的类型做不同的处理
        switch (aiAgentType) {
            case SINGLE_AGENT:
                // 单智能体处理逻辑
                handleSingleAgent(webSocketServer, agentCard, aiChatDTOReq);
                break;
            case MULTI_AGENT:
                // 多智能体处理逻辑
                handleMultiAgent(webSocketServer, agentCard, aiChatDTOReq);
                break;
            default:
                throw new IllegalArgumentException("未知的智能体类型: " + aiAgentType.getDesc());
        }
    }

    /**
     * 根据类型获取 ChatClient（优化版本）
     */
    private ChatClient getChatClient(AIAgentChoreographyType type, String message) {
        SearchRequest searchRequest = SearchRequest.builder()
                .topK(4)
                .similarityThresholdAll()
                .query(message)
                .build();

        // 检查 MCP 工具是否可用
        if (isMcpToolsAvailable()) {
            log.debug("MCP工具可用，使用完整工具集");
            return ChatClient.builder(chatModel)
                    .defaultToolCallbacks(tools)
                    .build();
        } else {
            log.warn("MCP工具不可用，使用基础ChatClient");
            return ChatClient.builder(chatModel)
                    .build();
        }
    }

    /**
     * 检查 MCP 工具是否可用
     */
    private boolean isMcpToolsAvailable() {
        try {
            // 优先使用健康检查状态
            if (mcpHealthCheckConfig != null && mcpHealthCheckConfig.isMcpServiceHealthy()) {
                return true;
            }
            
            // 如果健康检查不可用，尝试直接检查
            tools.getToolCallbacks();
            return true;
        } catch (Exception e) {
            log.warn("MCP工具不可用: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 检查会话是否在数据库中存在
     */
    private boolean isConversationExists(String conversationNo) {
        try {
            Conversation conversation = conversationMapper.selectById(conversationNo);
            boolean exists = conversation != null && !conversation.getDelFlag();
            log.debug("检查会话存在性 - ConversationNo: {}, Exists: {}", conversationNo, exists);
            return exists;
        } catch (Exception e) {
            log.error("检查会话存在性异常 - ConversationNo: {}, Error: {}", conversationNo, e.getMessage(), e);
            return false; // 异常时返回false，触发创建新会话
        }
    }

    /**
     * 创建新的会话记录
     */
    private String createNewConversation(String tenantId, String fromNo, AgentCard agentCard, String content, String conversationNo) {
        try {
            // 先查询这个会话ID是否已经存在
            Conversation existingConversation = conversationMapper.selectById(conversationNo);
            if (existingConversation != null && !existingConversation.getDelFlag()) {
                log.debug("会话已存在，无需创建 - ConversationNo: {}", conversationNo);
                return conversationNo;
            }
            

            // 创建会话记录，使用传入的conversationNo
            Conversation conversation = new Conversation();
            conversation.setSerialNo(conversationNo); // 使用传入的会话ID
            conversation.setTenantId(tenantId);
            conversation.setBizRoleTypeNo(fromNo);
            conversation.setAgentName(agentCard.getName());
            conversation.setAgentIconUrl(agentCard.getIconUrl());
            conversation.setBizRoleType("1"); // 默认用户类型
            conversation.setAgentNo(agentCard.getSerialNo());
            conversation.setStatus(1); // 活跃状态
            conversation.setTitle(extractTitleFromContent(content)); // 从消息内容提取标题
            conversation.setUnreadCount("1");
            conversation.setDelFlag(false);
            conversation.setCreateTime(new Date());

            // 插入会话记录
            int result = conversationMapper.insert(conversation);
            if (result > 0) {
                log.info("成功创建新会话 - ConversationNo: {}, AgentName: {}", conversation.getSerialNo());
                return conversationNo; // 返回传入的会话ID
            } else {
                log.error("创建会话失败 - AgentNo: {}, ConversationNo: {}", agentCard.getSerialNo(), conversationNo);
                return null;
            }
        } catch (Exception e) {
            log.error("创建会话异常 - AgentNo: {}, ConversationNo: {}, Error: {}", agentCard.getSerialNo(), conversationNo, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从消息内容中提取会话标题
     */
    private String extractTitleFromContent(String content) {
        if (content == null || content.trim().isEmpty()) {
            return "新对话";
        }
        
        // 取前20个字符作为标题，如果包含换行符则取第一行
        String title = content.trim();
        if (title.contains("\n")) {
            title = title.split("\n")[0];
        }
        if (title.length() > 20) {
            title = title.substring(0, 20) + "...";
        }
        return title;
    }

    /**
     * 保存用户消息到数据库
     */
    private String saveUserMessage(String tenantId, String fromNo, AgentCard agentCard, String conversationNo, String content) {
        // 判断是否需要保存一次会话信息
        // 检查数据库中是否存在该会话，不存在则需要先创建会话记录
        if (!isConversationExists(conversationNo)) {
            log.debug("会话不存在，创建新的会话记录 - ConversationNo: {}", conversationNo);
            String createdConversationNo = createNewConversation(tenantId, fromNo, agentCard, content, conversationNo);
            if (createdConversationNo == null) {
                log.error("创建会话失败，无法保存用户消息");
                return null;
            }
        }

        log.debug("保存用户消息 - ConversationNo: {}", conversationNo);
        ConversationMessage userMessage = new ConversationMessage();
        String messageSerialNo = UUID.randomUUID().toString().replace("-", "");
        userMessage.setSerialNo(messageSerialNo);
        userMessage.setConversationNo(conversationNo);
        userMessage.setTenantId(tenantId);
        userMessage.setBizRoleTypeNo(fromNo);
        userMessage.setAgentNo(agentCard.getSerialNo());
        userMessage.setRoleType("1"); // 用户消息
        userMessage.setContent(content);
        userMessage.setContentType("text");
        userMessage.setCreateTime(new Date());
        userMessage.setDelFlag(0);
        
        int result = conversationMessageMapper.insert(userMessage);
        if (result > 0) {
            // 更新会话的最后消息信息
            updateConversationLastMessage(conversationNo, messageSerialNo, content);
            log.debug("用户消息保存成功 - MessageNo: {}", messageSerialNo);
            return conversationNo;
        } else {
            log.error("用户消息保存失败 - ConversationNo: {}", conversationNo);
            return null;
        }
    }

    /**
     * 更新会话的最后消息信息
     */
    private void updateConversationLastMessage(String conversationNo, String messageNo, String messageContent) {
        try {
            Conversation conversation = new Conversation();
            conversation.setSerialNo(conversationNo);
            conversation.setLastMessageNo(messageNo);
            // 截取消息内容作为预览，最多50个字符
            String preview = messageContent != null && messageContent.length() > 50
                ? messageContent.substring(0, 50) + "..."
                : messageContent;
            conversation.setLastMessageContent(preview);

            conversationMapper.updateById(conversation);
            log.debug("更新会话最后消息信息 - ConversationNo: {}, MessageNo: {}", conversationNo, messageNo);
        } catch (Exception e) {
            log.error("更新会话最后消息信息失败 - ConversationNo: {}, Error: {}", conversationNo, e.getMessage(), e);
        }
    }

    /**
     * 保存AI响应消息到数据库
     */
    private String saveAIMessage(String tenantId, String fromNo, String agentNo, String conversationNo, String content) {
        log.debug("保存AI消息 - ConversationNo: {}", conversationNo);

        // 使用统一的extractDescription方法提取description字段，保持一致性
        String description = extractDescription(content);
        log.debug("提取的description: {}", description);

        ConversationMessage aiMessage = new ConversationMessage();
        String messageSerialNo = UUID.randomUUID().toString().replace("-", "");
        aiMessage.setSerialNo(messageSerialNo);
        aiMessage.setConversationNo(conversationNo);
        aiMessage.setTenantId(tenantId);
        aiMessage.setBizRoleTypeNo(fromNo);
        aiMessage.setAgentNo(agentNo);
        aiMessage.setRoleType("2"); // AI消息
        aiMessage.setContent(description);
        aiMessage.setContentType("text");
        aiMessage.setCreateTime(new Date());
        aiMessage.setDelFlag(0);
        
        int result = conversationMessageMapper.insert(aiMessage);
        if (result > 0) {
            // 更新会话的最后消息信息
            updateConversationLastMessage(conversationNo, messageSerialNo, description);
            log.debug("AI消息保存成功 - MessageNo: {}", messageSerialNo);
            return conversationNo;
        } else {
            log.error("AI消息保存失败 - ConversationNo: {}", conversationNo);
            return null;
        }
    }
    
    /**
     * 构建标准响应格式
     */
    private String buildStandardResponse(String aiResponse) {
        try {
            log.info("开始构建标准响应 - ResponseLength: {}", aiResponse != null ? aiResponse.length() : 0);
            
            // 根据AI响应内容智能判断返回类型
            ResponseType responseType = determineResponseType(aiResponse);
            String bizType = determineBizType(aiResponse);
            String content = formatContent(aiResponse, responseType);
            String description = extractDescription(aiResponse);
            
            log.info("响应类型分析 - Type: {}, BizType: {}, DescriptionLength: {}, ContentLength: {}", 
                responseType.getValue(), bizType, description.length(), content.length());
            
            // 构建标准JSON响应
            StringBuilder jsonBuilder = new StringBuilder();
            jsonBuilder.append("{");
            jsonBuilder.append("\"type\":\"").append(responseType.getValue()).append("\",");
            jsonBuilder.append("\"bizType\":\"").append(bizType).append("\",");
            jsonBuilder.append("\"description\":\"").append(escapeJsonString(description)).append("\",");
            jsonBuilder.append("\"content\":").append(content);
            jsonBuilder.append("}");
            
            String result = jsonBuilder.toString();
            log.info("标准响应构建完成 - ResultLength: {}", result.length());
            return result;
        } catch (Exception e) {
            log.error("构建标准响应格式失败 - ResponseLength: {}", aiResponse != null ? aiResponse.length() : 0, e);
            // 返回默认格式
            return "{\"type\":\"1\",\"bizType\":\"1\",\"description\":\"响应格式构建失败\",\"content\":\"响应格式构建失败\"}";
        }
    }
    
    /**
     * 响应类型枚举
     */
    private enum ResponseType {
        STRING("1", "字符串"),
        JSON_ARRAY("2", "json数组"),
        JSON_OBJECT("3", "json对象");
        
        private final String value;
        private final String desc;
        
        ResponseType(String value, String desc) {
            this.value = value;
            this.desc = desc;
        }
        
        public String getValue() { return value; }
        public String getDesc() { return desc; }
    }
    
    /**
     * 业务类型枚举
     */
    private enum BizType {
        PRODUCT("1", "商品"),
        COUPON("2", "优化券"),
        STORE("3", "门店"),
        GENERAL("4", "通用");
        
        private final String value;
        private final String desc;
        
        BizType(String value, String desc) {
            this.value = value;
            this.desc = desc;
        }
        
        public String getValue() { return value; }
        public String getDesc() { return desc; }
    }
    
    /**
     * 智能判断响应类型
     */
    private ResponseType determineResponseType(String aiResponse) {
        if (aiResponse == null || aiResponse.trim().isEmpty()) {
            return ResponseType.STRING;
        }
        
        String trimmed = aiResponse.trim();
        
        // 检查是否是JSON数组
        if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
            return ResponseType.JSON_ARRAY;
        }
        
        // 检查是否是JSON对象
        if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
            return ResponseType.JSON_OBJECT;
        }
        
        // 默认返回字符串
        return ResponseType.STRING;
    }
    
    /**
     * 智能判断业务类型
     */
    private String determineBizType(String aiResponse) {
        if (aiResponse == null) return BizType.PRODUCT.getValue();
        
        String lowerResponse = aiResponse.toLowerCase();
        
        // 根据关键词判断业务类型
        if (lowerResponse.contains("优化券") || lowerResponse.contains("券") || lowerResponse.contains("优惠") ||
            lowerResponse.contains("coupon") || lowerResponse.contains("discount")) {
            return BizType.COUPON.getValue();
        } else if (lowerResponse.contains("门店") || lowerResponse.contains("店铺") || lowerResponse.contains("地址") ||
                   lowerResponse.contains("store") || lowerResponse.contains("location") || lowerResponse.contains("address")) {
            return BizType.STORE.getValue();
        } else if (lowerResponse.contains("recommendedInfo") || lowerResponse.contains("goods") ||
                   lowerResponse.contains("products") || lowerResponse.contains("商品") ||
                   lowerResponse.contains("product") || lowerResponse.contains("item")) {
            return BizType.PRODUCT.getValue();
        } else {
            // 默认返回商品类型（保持原有逻辑不变）
            return BizType.PRODUCT.getValue();
        }
    }
    
    /**
     * 根据类型格式化内容
     */
    private String formatContent(String aiResponse, ResponseType responseType) {
        if (aiResponse == null) return "\"\"";
        
        switch (responseType) {
            case STRING:
                // 字符串类型，需要转义
                return "\"" + escapeJsonString(aiResponse) + "\"";
            case JSON_ARRAY:
            case JSON_OBJECT:
                // JSON类型，需要智能提取关键内容
                try {
                    // 验证JSON格式是否正确
                    var jsonNode = OBJECT_MAPPER.readTree(aiResponse);
                    
                    // 智能提取recommendedGoods等关键字段
                    String extractedContent = extractKeyContent(jsonNode);
                    if (extractedContent != null) {
                        return extractedContent;
                    }
                    
                    return aiResponse; // 如果没有找到关键字段，返回原始内容
                } catch (Exception e) {
                    log.warn("JSON格式验证失败，转换为字符串: {}", e.getMessage());
                    return "\"" + escapeJsonString(aiResponse) + "\"";
                }
            default:
                return "\"" + escapeJsonString(aiResponse) + "\"";
        }
    }
    
    /**
     * 验证并补全商品信息
     */
    private String validateAndCompleteGoodsInfo(String jsonContent) {
        try {
            var jsonNode = OBJECT_MAPPER.readTree(jsonContent);
            
            // 如果是recommendedInfo格式，验证并补全字段
            if (jsonNode.has(FIELD_RECOMMENDED_INFO) && jsonNode.get(FIELD_RECOMMENDED_INFO).isArray()) {
                return validateAndCompleteGoodsArray(jsonNode.get(FIELD_RECOMMENDED_INFO));
            }
            
            // 如果直接是商品数组，也进行补全
            if (jsonNode.isArray()) {
                return validateAndCompleteArray(jsonNode);
            }
            
            return jsonContent;
        } catch (Exception e) {
            log.warn("验证并补全商品信息失败: {}", e.getMessage());
            return jsonContent;
        }
    }

    /**
     * 验证并补全商品数组
     */
    private String validateAndCompleteGoodsArray(com.fasterxml.jackson.databind.JsonNode goodsArray) {
        for (int i = 0; i < goodsArray.size(); i++) {
            var good = goodsArray.get(i);
            completeGoodsFields(good, i);
        }
        return goodsArray.toString();
    }

    /**
     * 验证并补全数组（支持多种类型）
     */
    private String validateAndCompleteArray(com.fasterxml.jackson.databind.JsonNode jsonNode) {
        for (int i = 0; i < jsonNode.size(); i++) {
            var item = jsonNode.get(i);
            if (item.has(FIELD_GOODS_NAME)) { // 商品对象
                completeGoodsFields(item, i);
            } else if (item.has(FIELD_STORE_NAME)) { // 门店对象
                completeStoreFields(item, i);
            } else if (item.has(FIELD_COUPON_NAME)) { // 优惠券对象
                completeCouponFields(item, i);
            }
        }
        return jsonNode.toString();
    }

    /**
     * 补全商品字段
     */
    private void completeGoodsFields(com.fasterxml.jackson.databind.JsonNode good, int index) {
        var objectNode = (com.fasterxml.jackson.databind.node.ObjectNode) good;
        if (!good.has(FIELD_GOODS_NO)) {
            objectNode.put(FIELD_GOODS_NO, "G" + String.format("%03d", index + 1));
        }
        if (!good.has(FIELD_BRAND)) {
            objectNode.put(FIELD_BRAND, DEFAULT_BRAND);
        }
        if (!good.has(FIELD_STOCK)) {
            objectNode.put(FIELD_STOCK, DEFAULT_STOCK);
        }
    }

    /**
     * 补全门店字段
     */
    private void completeStoreFields(com.fasterxml.jackson.databind.JsonNode store, int index) {
        var objectNode = (com.fasterxml.jackson.databind.node.ObjectNode) store;
        if (!store.has(FIELD_STORE_NO)) {
            objectNode.put(FIELD_STORE_NO, "S" + String.format("%03d", index + 1));
        }
        if (!store.has(FIELD_ADDRESS)) {
            objectNode.put(FIELD_ADDRESS, DEFAULT_ADDRESS);
        }
    }

    /**
     * 补全优惠券字段
     */
    private void completeCouponFields(com.fasterxml.jackson.databind.JsonNode coupon, int index) {
        var objectNode = (com.fasterxml.jackson.databind.node.ObjectNode) coupon;
        if (!coupon.has(FIELD_COUPON_NO)) {
            objectNode.put(FIELD_COUPON_NO, "C" + String.format("%03d", index + 1));
        }
        if (!coupon.has(FIELD_VALIDITY_PERIOD)) {
            objectNode.put(FIELD_VALIDITY_PERIOD, DEFAULT_VALIDITY_PERIOD);
        }
    }

    /**
     * 智能提取JSON中的关键内容
     */
    private String extractKeyContent(com.fasterxml.jackson.databind.JsonNode jsonNode) {
        try {
            // 优先提取recommendedInfo字段
            if (jsonNode.has(FIELD_RECOMMENDED_INFO) && jsonNode.get(FIELD_RECOMMENDED_INFO).isArray()) {
                log.debug("找到recommendedInfo数组，提取作为主要内容");
                String content = jsonNode.get(FIELD_RECOMMENDED_INFO).toString();
                return validateAndCompleteGoodsInfo("{\"" + FIELD_RECOMMENDED_INFO + "\":" + content + "}");
            }
            
            // 如果整个响应就是一个商品数组，直接返回
            if (jsonNode.isArray()) {
                log.debug("响应本身就是商品数组，直接返回");
                return validateAndCompleteGoodsInfo(jsonNode.toString());
            }
            
            // 提取其他可能的字段
            String extractedContent = extractArrayField(jsonNode);
            if (extractedContent != null) {
                return extractedContent;
            }
            
            // 尝试提取对象字段
            String extractedObject = extractObjectField(jsonNode);
            if (extractedObject != null) {
                return extractedObject;
            }
            
            log.debug("未找到合适的字段，返回null");
            return null;
            
        } catch (Exception e) {
            log.warn("提取关键内容时发生异常: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 提取数组字段
     */
    private String extractArrayField(com.fasterxml.jackson.databind.JsonNode jsonNode) {
        String[] arrayFields = {FIELD_GOODS, FIELD_PRODUCTS, FIELD_STORES, FIELD_LOCATIONS, FIELD_COUPONS, FIELD_DISCOUNTS};
        
        for (String fieldName : arrayFields) {
            if (JsonProcessor.hasArrayField(jsonNode, fieldName)) {
                log.debug("找到数组字段: {}，提取作为主要内容", fieldName);
                return jsonNode.get(fieldName).toString();
            }
        }
        return null;
    }

    /**
     * 提取对象字段
     */
    private String extractObjectField(com.fasterxml.jackson.databind.JsonNode jsonNode) {
        var fieldNames = jsonNode.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            var fieldValue = jsonNode.get(fieldName);
            if (fieldValue.isObject()) {
                log.debug("找到对象字段: {}，提取作为主要内容", fieldName);
                return fieldValue.toString();
            }
        }
        return null;
    }

    /**
     * 提取AI响应的自然语言描述
     */
    private String extractDescription(String aiResponse) {
        if (aiResponse == null || aiResponse.trim().isEmpty()) {
            return "暂无描述";
        }
        
        try {
            // 尝试解析JSON，提取描述信息
            var jsonNode = OBJECT_MAPPER.readTree(aiResponse);
            
            // 优先提取description字段作为描述（新的大模型返回格式）
            String description = extractFieldValue(jsonNode, "description");
            if (description != null && !description.trim().isEmpty()) {
                return description;
            }
            
            // 兼容旧格式：提取topRecommendation字段作为描述
            String topRec = extractFieldValue(jsonNode, "topRecommendation");
            if (topRec != null) {
                return topRec;
            }
            
            // 提取message字段作为描述
            String message = extractFieldValue(jsonNode, "message");
            if (message != null) {
                return message;
            }
            
            // 提取userPreference字段作为描述
            String userPref = extractFieldValue(jsonNode, "userPreference");
            if (userPref != null) {
                return userPref;
            }
            
            // 如果没有找到特定字段，尝试生成描述
            String generatedDescription = generateDescriptionFromContent(jsonNode);
            if (generatedDescription != null) {
                return generatedDescription;
            }
            
            // 默认返回一个通用描述
            return DEFAULT_DESCRIPTION;
            
        } catch (Exception e) {
            // 如果不是JSON格式，返回原始响应的前100个字符作为描述
            String trimmed = aiResponse.trim();
            if (trimmed.length() > 100) {
                return trimmed.substring(0, 100) + "...";
            }
            return trimmed;
        }
    }

    /**
     * 提取字段值
     */
    private String extractFieldValue(com.fasterxml.jackson.databind.JsonNode jsonNode, String fieldName) {
        return JsonProcessor.getTextValue(jsonNode, fieldName);
    }

    /**
     * 从内容生成描述
     */
    private String generateDescriptionFromContent(com.fasterxml.jackson.databind.JsonNode jsonNode) {
        // 处理recommendedInfo数组
        if (jsonNode.has(FIELD_RECOMMENDED_INFO) && jsonNode.get(FIELD_RECOMMENDED_INFO).isArray()) {
            return generateDescriptionFromArray(jsonNode.get(FIELD_RECOMMENDED_INFO), FIELD_GOODS_NAME, "款商品");
        }
        
        // 如果整个响应就是数组，生成描述
        if (jsonNode.isArray() && jsonNode.size() > 0) {
            var firstItem = jsonNode.get(0);
            if (firstItem.has(FIELD_GOODS_NAME)) {
                return generateDescriptionFromArray(jsonNode, FIELD_GOODS_NAME, "款商品");
            } else if (firstItem.has(FIELD_STORE_NAME)) {
                return generateDescriptionFromArray(jsonNode, FIELD_STORE_NAME, "家门店");
            } else if (firstItem.has(FIELD_COUPON_NAME)) {
                return generateDescriptionFromArray(jsonNode, FIELD_COUPON_NAME, "个优惠活动");
            }
        }
        
        return null;
    }

    /**
     * 从数组生成描述
     */
    private String generateDescriptionFromArray(com.fasterxml.jackson.databind.JsonNode array, String nameField, String unit) {
        if (array.size() > 0) {
            var firstItem = array.get(0);
            if (firstItem.has(nameField)) {
                String name = firstItem.get(nameField).asText();
                if (array.size() == 1) {
                    return "为您推荐了" + name;
                } else {
                    return "为您推荐了" + name + "等" + array.size() + unit;
                }
            }
        }
        return null;
    }

    /**
     * 转义JSON字符串中的特殊字符
     */
    private String escapeJsonString(String input) {
        if (input == null) return "";
        return input.replace("\\", "\\\\")
                   .replace("\"", "\\\"")
                   .replace("\n", "\\n")
                   .replace("\r", "\\r")
                   .replace("\t", "\\t");
    }

    /**
     * 获取格式要求字符串
     */
    private String getFormatRequirements() {
        try {
            return goodsRecommendation.getContentAsString(StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("加载格式要求文件失败", e);
            throw new RuntimeException("加载格式要求文件失败", e);
        }
    }

    /**
     * JSON处理工具类
     */
    private static class JsonProcessor {
        
        /**
         * 安全地解析JSON字符串
         */
        public static com.fasterxml.jackson.databind.JsonNode parseJson(String jsonString) {
            try {
                return OBJECT_MAPPER.readTree(jsonString);
            } catch (Exception e) {
                log.warn("JSON解析失败: {}", e.getMessage());
                return null;
            }
        }
        
        /**
         * 检查JSON节点是否包含指定字段且为数组
         */
        public static boolean hasArrayField(com.fasterxml.jackson.databind.JsonNode node, String fieldName) {
            return node != null && node.has(fieldName) && node.get(fieldName).isArray();
        }
        
        /**
         * 检查JSON节点是否包含指定字段且为文本
         */
        public static boolean hasTextField(com.fasterxml.jackson.databind.JsonNode node, String fieldName) {
            return node != null && node.has(fieldName) && node.get(fieldName).isTextual();
        }
        
        /**
         * 安全地获取文本字段值
         */
        public static String getTextValue(com.fasterxml.jackson.databind.JsonNode node, String fieldName) {
            if (hasTextField(node, fieldName)) {
                String value = node.get(fieldName).asText();
                return (value != null && !value.trim().isEmpty()) ? value : null;
            }
            return null;
        }
        
        /**
         * 安全地获取数组字段
         */
        public static com.fasterxml.jackson.databind.JsonNode getArrayField(com.fasterxml.jackson.databind.JsonNode node, String fieldName) {
            return hasArrayField(node, fieldName) ? node.get(fieldName) : null;
        }
    }

}
